package se.cth.hedgehogphoto.geocoding.view; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.MouseAdapter; import java.net.URL; import java.util.List; import java.util.logging.Level; import javax.swing.BorderFactory; import javax.swing.DefaultComboBoxModel; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.SwingUtilities; import se.cth.hedgehogphoto.geocoding.model.URLCreator; import se.cth.hedgehogphoto.geocoding.model.XMLParser; import se.cth.hedgehogphoto.log.Log; import se.cth.hedgehogphoto.objects.LocationGPSObject; /** * The MainView in the geocoding-subsystem. * @author Florian Minges */ @SuppressWarnings("serial") public final class GeoSearchPanel extends JPanel { private static GeoSearchPanel instance; private static JFrame frame; private ConstrainedGrid resultPanel = new ConstrainedGrid(); private JComboBox<Object> searchBox = new JComboBox<Object>(); private JButton okButton; private JButton cancelButton; private URLCreator urlCreator = URLCreator.getInstance(); private XMLParser xmlParser = XMLParser.getInstance(); private String oldSearch = ""; private boolean searching; public static GeoSearchPanel getInstance() { if (instance == null) { instance = new GeoSearchPanel(); } instance.setVisible(true); return instance; } private GeoSearchPanel() { super(new BorderLayout(8, 8)); setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); setBackground(Color.white); JPanel topPanel = new JPanel(new BorderLayout(4, 4)); topPanel.setOpaque(false); topPanel.add(new JLabel("Find:"), BorderLayout.WEST); topPanel.add(this.searchBox, BorderLayout.CENTER); add(topPanel, BorderLayout.NORTH); add(this.resultPanel, BorderLayout.CENTER); this.searchBox.setEditable(true); Component editorComponent = this.searchBox.getEditor().getEditorComponent(); this.searchBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { doSearch(searchBox.getSelectedItem()); } }); if (editorComponent instanceof JTextField) { final JTextField textField = (JTextField) editorComponent; textField.addFocusListener(new FocusAdapter() { public void focusGained(FocusEvent e) { textField.selectAll(); } }); } this.okButton = new JButton("Ok"); this.cancelButton = new JButton("Cancel"); this.okButton.setEnabled(false); JPanel buttonWrapper = new JPanel(); buttonWrapper.add(this.okButton); buttonWrapper.add(this.cancelButton); add(buttonWrapper, BorderLayout.SOUTH); createFrame(); } public void createFrame() { GeoSearchPanel.frame = new JFrame(); GeoSearchPanel.frame.setPreferredSize(new Dimension(400,600)); GeoSearchPanel.frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); GeoSearchPanel.frame.getContentPane().add(this); GeoSearchPanel.frame.pack(); GeoSearchPanel.frame.getContentPane().setVisible(true); GeoSearchPanel.frame.setVisible(true); } @Override public void setVisible(boolean state) { super.setVisible(state); if (frame != null) { frame.setVisible(state); } } public void addOkButtonListener(ActionListener listener) { this.okButton.addActionListener(listener); } public void addCancelButtonListener(ActionListener listener) { this.cancelButton.addActionListener(listener); } public void enableOkButton(boolean state) { this.okButton.setEnabled(state); } public void doSearch(Object selectedItem) { if (this.searching) { return; } final String newSearch = selectedItem == null ? "" : selectedItem .toString(); if (this.oldSearch.equals(newSearch)) { return; } this.oldSearch = newSearch; Runnable runnable = new Runnable() { public void run() { doSearchInternal(newSearch); } }; this.searching = true; this.searchBox.setEnabled(false); this.searchBox.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); Thread thread = new Thread(runnable, "searcher " + newSearch); thread.start(); } private void doSearchInternal(final String newSearch) { try { // Create a URL for the desired page, and create objects for the searchResults URL url = this.urlCreator.queryGeocodingURL(newSearch); List<LocationGPSObject> locations = xmlParser.processGeocodingSearch(url); this.resultPanel.addLocations(locations); this.setPreferredWidth(); } catch (Exception e) { Log.getLogger().log(Level.SEVERE, "failed to search for \"" + newSearch + "\"", e); } Runnable runnable = new Runnable() { public void run() { try { DefaultComboBoxModel comboBoxModel = (DefaultComboBoxModel)searchBox.getModel(); comboBoxModel.removeElement(newSearch); comboBoxModel.addElement(newSearch); } finally { searchBox.setCursor(Cursor.getDefaultCursor()); searching = false; searchBox.setEnabled(true); } } }; SwingUtilities.invokeLater(runnable); } public void setInitialSearchBoxText(final String text) { if (text == null) { return; } Object object = new Object() { public String toString() { return text; } }; this.searchBox.addItem(object); this.searchBox.setSelectedItem(object); doSearch(this.searchBox.getSelectedItem()); } private void setPreferredWidth() { Dimension dimension = this.getPreferredSize(); dimension.width = this.resultPanel.getPreferredWidth() + 30; } public void addResultPanelMouseListener(MouseAdapter adapter) { this.resultPanel.setMouseAdapter(adapter); } }